/*
** Copyright (C) 2010 Calin Radoni
**
** This file is part of CHScanner.
**
** CHScanner is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** CHScanner is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with CHScanner. If not, see <http://www.gnu.org/licenses/>.
*/

//---------------------------------------------------------------------------
#include "stdafx.h"
//---------------------------------------------------------------------------
#include <stdio.h>
#include <windows.h>
//---------------------------------------------------------------------------
#include "MCVersionReader.h"
//---------------------------------------------------------------------------


//---------------------------------------------------------------------------
MCVersionReader::MCVersionReader(void)
{
	InternalOk = false;
	ExternalOk = false;
}

MCVersionReader::~MCVersionReader(void)
{
}
//---------------------------------------------------------------------------



//---------------------------------------------------------------------------
// Retrieve version info for current application
//---------------------------------------------------------------------------
void MCVersionReader::GetInternalData(CString File)
{
	GetVersionInfo(File, true);
}
//---------------------------------------------------------------------------
// Retrieve version info for the specified file
//---------------------------------------------------------------------------
void MCVersionReader::GetExternalData(CString File)
{
	GetVersionInfo(File, false);
}
//---------------------------------------------------------------------------



//---------------------------------------------------------------------------
// Retrieve version information
//---------------------------------------------------------------------------
void MCVersionReader::GetVersionInfo(CString File, bool Internal)
{
DWORD Size, Zero;
BYTE *Data;
BOOL res;
VS_FIXEDFILEINFO* fixInfo;
unsigned int uSize;

#ifdef _DEBUG
	DWORD err;
#endif

	if(Internal){
		LanguageID         = "";
		ProductName        = "";
		VersionNumber      = "";
		ReleaseNumber      = "";
		BuildNumber        = "";
		FileDescription    = "";
		CompanyName        = "";
		LegalCopyright     = "";
		LegalTrademarks    = "";
		ContactPhone       = "";
		ContactMail        = "";
		ContactWeb         = "";
		FileFlagDebug      = false;
		FileFlagPrerelease = false;
	}
	else{
		extFileVersion      = "";
		extFileDescription  = "";
		extLegalCopyright   = "";
		extCompanyName      = "";
		extInternalName     = "";
		extLanguageID       = "";
		extLegalTrademarks  = "";
		extOriginalFilename = "";
		extProductName      = "";
		extProductVersion   = "";
		extComments         = "";
		FileFlagDebug       = false;
		FileFlagPrerelease  = false;
	}

	if(Internal) InternalOk = false;
	else         ExternalOk = false;

	Size = GetFileVersionInfoSize(File, &Zero);
	if(Size==0){
		#ifdef _DEBUG
			err = GetLastError();
			err = err;
		#endif
		return;
	}

	Data = new BYTE[Size+1];
	res  = GetFileVersionInfo(File, Zero, Size, Data);
	if(!res){
		delete[] Data;
		return;
	}

	res = VerQueryValue(Data, "\\", (void**)&fixInfo, &uSize);
	if(!res){
		delete[] Data;
		return;
	}

DWORD dwFileFlagsMask;
DWORD dwFileFlags;
	dwFileFlagsMask = fixInfo->dwFileFlagsMask;
	dwFileFlags     = fixInfo->dwFileFlags;
	dwFileFlags     = dwFileFlags & dwFileFlagsMask;

	if(dwFileFlags & VS_FF_DEBUG){
		FileFlagDebug = true;
	}
	else{
		FileFlagDebug = false;
	}

	if(dwFileFlags & VS_FF_PRERELEASE){
		FileFlagPrerelease = true;
	}
	else{
		FileFlagPrerelease = false;
	}

int BuildNo, ReleaseNo, MinorNo, MajorNo;
	BuildNo   = (int)LOWORD(fixInfo->dwFileVersionLS);
	ReleaseNo = (int)HIWORD(fixInfo->dwFileVersionLS);
	MinorNo   = (int)LOWORD(fixInfo->dwFileVersionMS);
	MajorNo   = (int)HIWORD(fixInfo->dwFileVersionMS);

	if(Internal){
		VersionNumber.Format(_T("%d.%d"), MajorNo, MinorNo);
		ReleaseNumber.Format(_T("%d"),    ReleaseNo);
		BuildNumber.Format  (_T("%d"),    BuildNo);
	}
	else{
		extFileVersion.Format(_T("%d.%d.%d.%d"), MajorNo, MinorNo, ReleaseNo, BuildNo);
	}

	ComputeLanguage(Data, Internal);
	if(Internal){
		if(LanguageID==""){
			delete[] Data;
			InternalOk = true;
			return;
		}
	}
	else{
		if(extLanguageID==""){
			delete[] Data;
			ExternalOk = true;
			return;
		}
	}

	if(Internal){
		ProductName     = ComputeInfo(Data, Internal, "ProductName");
		FileDescription = ComputeInfo(Data, Internal, "FileDescription");
		CompanyName     = ComputeInfo(Data, Internal, "CompanyName");
		LegalCopyright  = ComputeInfo(Data, Internal, "LegalCopyright");
		LegalTrademarks = ComputeInfo(Data, Internal, "LegalTrademarks");
		ContactPhone    = ComputeInfo(Data, Internal, "ContactPhone");
		ContactMail     = ComputeInfo(Data, Internal, "ContactMail");
		ContactWeb		= ComputeInfo(Data, Internal, "ContactWeb");
	}
	else{
		extFileDescription	= ComputeInfo(Data, Internal, "FileDescription");
		extLegalCopyright	= ComputeInfo(Data, Internal, "LegalCopyright");
		extCompanyName		= ComputeInfo(Data, Internal, "CompanyName");
		extInternalName		= ComputeInfo(Data, Internal, "InternalName");
		extLegalTrademarks	= ComputeInfo(Data, Internal, "LegalTrademarks");
		extOriginalFilename	= ComputeInfo(Data, Internal, "OriginalFilename");
		extProductName		= ComputeInfo(Data, Internal, "ProductName");
		extProductVersion	= ComputeInfo(Data, Internal, "ProductVersion");
		extComments			= ComputeInfo(Data, Internal, "Comments");
    }

    delete[] Data;
    if(Internal) InternalOk = true;
    else         ExternalOk = true;
}
//---------------------------------------------------------------------------
// Conversion routine : BYTE -> AnsiString(HEXA)
//---------------------------------------------------------------------------
CString MCVersionReader::btohas(BYTE val){
CString res;
char mmm[2];
BYTE vvv;

	res.Empty();

	vvv  = (BYTE)(val>>4);
	vvv &= 0x0F;
	if(vvv>9) mmm[0] = (char)('A' + vvv - 10);
	else      mmm[0] = (char)('0' + vvv);
	mmm[1] = 0;
	res += mmm;

	vvv  = val;
	vvv &= 0x0F;
	if(vvv>9) mmm[0] = (char)('A' + vvv - 10);
	else      mmm[0] = (char)('0' + vvv);
	mmm[1] = 0;
	res += mmm;

	return res;
}
//---------------------------------------------------------------------------
// Retrieve language name
//---------------------------------------------------------------------------
void MCVersionReader::ComputeLanguage(BYTE* Data, bool Internal){
BOOL res;
BYTE* info;
unsigned int iSize;
CString aux;

	if(Internal) LanguageID    = "";
    else         extLanguageID = "";

	res = VerQueryValue(Data, "\\VarFileInfo\\Translation", (void**)&info, &iSize);
    if(!res) return;
    if(iSize<4) return;

	aux  = btohas(info[1]);
	aux += btohas(info[0]);
	aux += btohas(info[3]);
    aux += btohas(info[2]);
    if(Internal) LanguageID    = aux;
    else         extLanguageID = aux;
}
//---------------------------------------------------------------------------
// Retrieve requested info
//---------------------------------------------------------------------------
CString MCVersionReader::ComputeInfo(BYTE* Data, bool Internal, CString Name){
CString str;
BYTE* info;
unsigned int iSize, i;
char mmm[2];
BOOL res;

	if(Internal){
		if(LanguageID=="") return "";
    }
    else{
		if(extLanguageID=="") return "";
    }

	str = "\\StringFileInfo\\";
    if(Internal) str += LanguageID;
    else         str += extLanguageID;
    str += "\\";
    str += Name;
    res = VerQueryValue(Data, (LPTSTR)(LPCTSTR)str, (void**)&info, &iSize);
    if(!res) return "";

    str = "";
    mmm[1] = 0;
    for(i=0; i<iSize && (char)info[i]!=0; i++){
    	mmm[0] = (char)info[i];
        str += mmm;
    }
    return str;
}
//---------------------------------------------------------------------------

